public with sharing class Cald_EditPayoutVF
{
    private final Callidus_Plan__c[] plan = new Callidus_Plan__c[1];
    
    public Callidus_Plan__c planObj {get; set;}
    public Callidus_Rate__c rateObj {get; set;}
    public String rateType {get; set;}
    
    public Boolean displayAttainmentTable {get; set;}
    public Boolean displayCreditTable {get; set;}
    public Boolean deleteTierFlag {get; set;}
    public Boolean rateTypeFlag {get; set;}
    public Boolean showAttainmentSymbol {get; set;} 
    public String attainmentSymbol {get{ attainmentSymbol = '%'; return attainmentSymbol;} set;}
    
    public List<AttainmentWrapper> payoutAttainmentList {get; set;}
    public List<CreditWrapper> payoutCreditList {get; set;}
    private List<AttainmentWrapper> attainmentList = new List<AttainmentWrapper>();
    private List<CreditWrapper> creditList = new List<CreditWrapper>();
    
    public Cald_EditPayoutVF(ApexPages.StandardController myController)
    {
        plan[0] = (Callidus_Plan__c)myController.getRecord();
        planObj = [select id, Quota__c, OTE__c from Callidus_Plan__c where id = :plan[0].id];

        displayAttainmentTable = true;
        displayCreditTable = false;
        rateTypeFlag = false;
        deleteTierFlag = true;
        
        if(payoutAttainmentList == null)
            payoutAttainmentList = new List<AttainmentWrapper>();
        if(payoutCreditList == null)
            payoutCreditList = new List<CreditWrapper>();
        
        Callidus_Rate__c[]  rateList = [select Min_Attainment__c, Max_Attainment__c, Min_Credit__c, Max_Credit__c, Rate_Type__c, Rate__c from Callidus_Rate__c where Plan__c = :plan[0].id];
        Callidus_Rate__c[] dupRateList = rateList.deepClone();
        rateList.clear();
        Integer i = 0;
        Integer dupSize = dupRateList.size();
        String rType = null;
        if(dupSize > 0)
        	rType = dupRateList[0].Rate_Type__c;
        	 
        while(dupSize != rateList.size())
        {
        	if(rType == 'Attainment')
        	{
	        	i = 0;
	        	for(Callidus_Rate__c cr: dupRateList)
	        	{
	        		if(rateList.size() > 0 && (cr.Min_Attainment__c == rateList[rateList.size()-1].Max_Attainment__c))
	        		{
	        			rateList.add(cr);
	        			break;
	        		}
	        		if(cr.Min_Attainment__c == 0)
	        		{
	        			rateList.add(cr);
	        			break;
	        		}
	        	}
				dupRateList.remove(i);
	    		i++;
        	}
        	else
        	{
	        	i = 0;
	        	for(Callidus_Rate__c cr: dupRateList)
	        	{
	        		if(rateList.size() > 0 && (cr.Min_Credit__c == rateList[rateList.size()-1].Max_Credit__c))
	        		{
	        			rateList.add(cr);
	        			break;
	        		}
	        		if(cr.Min_Credit__c == 0)
	        		{
	        			rateList.add(cr);
	        			break;
	        		}
	        	}
				dupRateList.remove(i);
	    		i++;
        	}
        }
        
        if(rateList.size() > 0)
        {
            rateType = rateList[0].Rate_Type__c;
            rateTypeFlag = !rateTypeFlag;
            if(rateList[0].Rate_Type__c == 'Credit')
            {
                for(Callidus_Rate__c r: rateList)
                {
                    CreditWrapper c =  new CreditWrapper(String.valueOf(r.Min_Credit__c), String.valueOf(r.Max_Credit__c), String.valueOf(r.Rate__c), true);
                    payoutCreditList.add(c);
                }
                displayAttainmentTable = !displayAttainmentTable;
                displayCreditTable = !displayCreditTable;
                
                if(payoutCreditList.size() > 1)
                    deleteTierFlag = !deleteTierFlag;
                
            }
            else
            {
                for(Callidus_Rate__c r: rateList)
                {
                    AttainmentWrapper a = new AttainmentWrapper(String.valueOf(r.Min_Attainment__c), String.valueOf(r.Max_Attainment__c), String.valueOf(r.Rate__c), true);
                    payoutAttainmentList.add(a);
                }
                if(payoutAttainmentList.size() > 1)
                    deleteTierFlag = !deleteTierFlag;
            }
        }
        else
        {
            payoutAttainmentList.add(new AttainmentWrapper(String.valueOf(0), String.valueOf(0), String.valueOf(0), true));
            //ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, ''+rateList.size()+' -- '+payoutAttainmentList.size()));         
        }
        //ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, ''+payoutAttainmentList));
        if(displayAttainmentTable)
            showAttainmentSymbol = true;
    }
    
    public List<SelectOption> getRateTypeList()
    {
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('Attainment', 'Attainment'));
        options.add(new SelectOption('Credit', 'Credit'));
        return options;
    }
    
    public PageReference updateRateTable()
    {
        if(rateType == 'Attainment')
        {
            String maxVal = '';
            for(AttainmentWrapper a: payoutAttainmentList)
            {
                if(maxVal != '')
                {
                    a.min = maxVal;
                    if(Double.valueOf(maxVal) > Double.valueOf(a.max))
                        ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'Max Attainment should be >= Min Attainment in each tier.'));
                }
                maxVal = a.max;
            }
        }
        else
        {
            String maxVal = '';
            for(CreditWrapper c: payoutCreditList)
            {
                if(maxVal != '')
                {
                    c.min = maxVal;
                    if(Double.valueOf(maxVal) > Double.valueOf(c.max))
                        ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'Max Credit should be >= Min Credit in each tier.'));
                }
                maxVal = c.max;
            }
        }
            
        return null;
    }

    public PageReference addTier()
    {
        if(rateType == 'Attainment')
        {
            String adjVal = payoutAttainmentList.get(payoutAttainmentList.size() - 1).Max;
            payoutAttainmentList.add(new AttainmentWrapper(adjVal, adjVal, payoutAttainmentList.get(payoutAttainmentList.size() - 1).Rate, true));
        }
        else
        {
            String adjVal = payoutCreditList.get(payoutCreditList.size() - 1).Max;
            payoutCreditList.add(new CreditWrapper(adjVal, adjVal, payoutCreditList.get(payoutCreditList.size() - 1).Rate, true));
        }
            
        if(deleteTierFlag)
            deleteTierFlag = !deleteTierFlag;
        return null;
    }
    
    public PageReference deleteTier()
    {
        if(rateType == 'Attainment' && payoutAttainmentList.size() > 1)
            payoutAttainmentList.remove(payoutAttainmentList.size() - 1);
        else if(payoutCreditList.size() > 1)
            payoutCreditList.remove(payoutCreditList.size() - 1);
            
        if(payoutAttainmentList.size() == 1 || payoutCreditList.size() == 1 && !deleteTierFlag)
            deleteTierFlag = !deleteTierFlag;
        return null;
    }
    
    public class AttainmentWrapper
    {
        public String min {get; set;}
        public String max {get; set;}
        public String Rate {get; set;}
        public Boolean disableAttainmentFlag {get; set;}
        public AttainmentWrapper(String minimum, String maximum, String R, Boolean flag)
        {
            min = minimum;
            max = maximum;
            Rate = R;
            disableAttainmentFlag = flag;
        }
    }
    
    public class CreditWrapper
    {
        public String min {get; set;}
        public String max {get; set;}
        public String Rate {get; set;}
        public Boolean disableCreditFlag {get; set;}
        public CreditWrapper(String minimum, String maximum, String R, Boolean flag)
        {
            min = minimum;
            max = maximum;
            Rate = R;
            disableCreditFlag = flag;
        }

    }

    public List<AttainmentWrapper> getAttainmentRows() {
        return payoutAttainmentList;
    }
    
    public List<CreditWrapper> getCreditRows() {
        return payoutCreditList;
    }

    public PageReference checkSelection()
    {
        displayAttainmentTable = !displayAttainmentTable;
        displayCreditTable = !displayCreditTable;
        if(rateType == 'Attainment')
        {
            for(CreditWrapper aw: payoutCreditList)
                creditList.add(aw);
            payoutCreditList.clear();
            if(attainmentList.size() > 0)
            {
                for(AttainmentWrapper aw: attainmentList)
                    payoutAttainmentList.add(aw);
                attainmentList.clear();
            }
            if(payoutAttainmentList.size() <= 1)
                deleteTierFlag = true;
            else
                deleteTierFlag = false;
        }
        else
        {
            for(AttainmentWrapper aw: payoutAttainmentList)
                attainmentList.add(aw);
            payoutAttainmentList.clear();                    

            if(creditList.size() == 0 && payoutCreditList.size() == 0)
            {
                payoutCreditList.add(new CreditWrapper(String.valueOf(0), String.valueOf(0), String.valueOf(0), true));
            }
            
            if(creditList.size() > 0)
            {
                for(CreditWrapper aw: creditList)
                    payoutCreditList.add(aw);
                creditList.clear();
            }
            
            if(payoutCreditList.size() <= 1)
                deleteTierFlag = true;
            else
                deleteTierFlag = false;
        }
        
        if(displayAttainmentTable)
            showAttainmentSymbol = true;
        else
            showAttainmentSymbol = false;
        return null;
    }    

    public PageReference save()
    {
        try
        {
            Callidus_Rate__c[] deleteRateList = new Callidus_Rate__c[]{};
            if(rateType == 'Attainment' && planObj.Quota__c == null)
            {
                ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.error, 'Please enter the Quota.'));
                return null;
            }
            for(Callidus_Rate__c[] rList : [select id from Callidus_Rate__c where Plan__c = :plan[0].id])
            {
                deleteRateList = rList;
            }
                
            Callidus_Rate__c[] newRateList = new Callidus_Rate__c[]{};
            update planObj;
                    
            if(rateType == 'Attainment')
            {
                for(AttainmentWrapper aw: payoutAttainmentList)
                {
                    if(Double.valueOf(aw.min) >= 0 && Double.valueOf(aw.max) >= 0 && Double.valueOf(aw.Rate) >= 0)
                    {
                        Callidus_Rate__c rate = new Callidus_Rate__c(Plan__c = plan[0].Id, Min_Attainment__c = Double.valueOf(aw.min), Max_Attainment__c = Double.valueOf(aw.max), Rate__c = Double.valueOf(aw.Rate), Rate_Type__c = rateType);
                        newRateList.add(rate);                    
                    }      
                    //ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, ''+newRateList.size()));         
                }
            }
            else
            {
                for(CreditWrapper cw: payoutCreditList)
                {
                    if(Double.valueOf(cw.min) >= 0 && Double.valueOf(cw.max) >= 0 && Double.valueOf(cw.Rate) >= 0)
                    {
                        Callidus_Rate__c rate = new Callidus_Rate__c(Plan__c = plan[0].Id, Min_Credit__c = Double.valueOf(cw.min), Max_Credit__c = Double.valueOf(cw.max), Rate__c = Double.valueOf(cw.Rate), Rate_Type__c = rateType);
                        newRateList.add(rate);                    
                    }               
                }
            }
            
            if(newRateList.size() > 0)
            {
                    insert newRateList;
            }
            //ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'Rate List.'+newRateList));
            delete deleteRateList;//delete the earlier RateList defined for the Plan
        }
        catch(Exception e)
        {
            if(e.getMessage().indexOf('Invalid double') != -1)
                ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'Please enter numeric values.'));
            else
                ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));           
        }
        return null;
    }

    static testMethod void testCald_EditPayoutVF()
    {
        
        PageReference pg = Page.Cald_Edit_Payout;
        Test.setCurrentPage(pg);
		Test.startTest();        
        Callidus_Plan__c plan = new Callidus_Plan__c(Name = 'Test', Start_Date__c = Date.today(), End_Date__c = (Date.today() + 100), Quota__c = 1000000, Type__c = 'byRole');
        insert plan;
		List<Callidus_Plan__c> tPlan = [select Name from Callidus_Plan__c where id = :plan.id];
		for(Callidus_Plan__c p:tPlan)
		{
			System.assertEquals('Test', p.Name);
		}
        
        Callidus_Rate__c rate = new Callidus_Rate__c(Plan__c = plan.id, Min_Attainment__c = 0, Max_attainment__c = 100, Rate__c = 1, Rate_Type__c = 'Attainment');
        insert rate;
		List<Callidus_Rate__c> tRate = [select Rate_Type__c from Callidus_Rate__c where Plan__c = :plan.id];
		for(Callidus_Rate__c p:tRate)
		{
			System.assertEquals('Attainment', p.Rate_Type__c);
		}

        rate = new Callidus_Rate__c(Plan__c = plan.id, Min_Attainment__c = 100, Max_attainment__c = 110, Rate__c = 2, Rate_Type__c = 'Attainment');
        insert rate;
		tRate = [select Rate_Type__c from Callidus_Rate__c where Plan__c = :plan.id];
		for(Callidus_Rate__c p:tRate)
		{
			System.assertEquals('Attainment', p.Rate_Type__c);
		}
        
        ApexPages.StandardController mc = new Apexpages.Standardcontroller(plan);
        Cald_EditPayoutVF ep = new Cald_EditPayoutVF(mc);
        ep.rateType = 'Attainment';
        system.assertEquals('Attainment', ep.rateType);
        system.assertEquals(null, ep.addTier());
        
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('Attainment', 'Attainment'));
        options.add(new SelectOption('Credit', 'Credit'));
        system.assertEquals(options.get(0).getValue(), ep.getRateTypeList().get(0).getValue());
        
        system.assertEquals(ep.payoutAttainmentList ,ep.getAttainmentRows());
        system.assertEquals(ep.payoutCreditList, ep.getCreditRows());
        system.assertEquals(null, ep.updateRateTable());
        system.assertEquals(null, ep.checkSelection());
        system.assertEquals(null, ep.save());
        system.assertEquals(null, ep.deleteTier());
        Callidus_Plan_Assignable__c cp = new Callidus_Plan_Assignable__c(Plan__c = plan.id);
        insert cp;
        Callidus_Plan_Assignable__c[] cpList = [select Plan__c from Callidus_Plan_Assignable__c where id = :cp.id];
        for(Callidus_Plan_Assignable__c cpa:cpList)
        	system.assertEquals(plan.id, cpa.Plan__c);
        try
        {
        	delete plan;
        }
        catch(Exception e)
        {
        }
        system.assertEquals('Test', plan.Name);
        
        plan = new Callidus_Plan__c(Name = 'Test', Start_Date__c = Date.today(), End_Date__c = (Date.today() + 100), Quota__c = 1000000, Type__c = 'byTitle');
        insert plan;
		tPlan = [select Name from Callidus_Plan__c where id = :plan.id];
		for(Callidus_Plan__c p:tPlan)
		{
			System.assertEquals('Test', p.Name);
		}
        
        rate = new Callidus_Rate__c(Plan__c = plan.id, Min_Credit__c = 0, Max_Credit__c = 100000, Rate__c = 1, Rate_Type__c = 'Credit');
        insert rate;
		tRate = [select Rate_Type__c from Callidus_Rate__c where Plan__c = :plan.id];
		for(Callidus_Rate__c p:tRate)
		{
			System.assertEquals('Credit', p.Rate_Type__c);
		}
        
        rate = new Callidus_Rate__c(Plan__c = plan.id, Min_Credit__c = 100000, Max_Credit__c = 110000, Rate__c = 2, Rate_Type__c = 'Credit');
        insert rate;
		tRate = [select Rate_Type__c from Callidus_Rate__c where Plan__c = :plan.id];
		for(Callidus_Rate__c p:tRate)
		{
			System.assertEquals('Credit', p.Rate_Type__c);
		}

        mc = new Apexpages.Standardcontroller(plan);
        ep = new Cald_EditPayoutVF(mc);
        ep.rateType = 'Credit';
        system.assertEquals('Credit', ep.rateType);
        system.assertEquals(null, ep.addTier());
        system.assertEquals(options.get(1).getValue(), ep.getRateTypeList().get(1).getValue());
        system.assertEquals(ep.payoutAttainmentList ,ep.getAttainmentRows());
        system.assertEquals(ep.payoutCreditList, ep.getCreditRows());
        system.assertEquals(null, ep.updateRateTable());
        system.assertEquals(null, ep.checkSelection());
        system.assertEquals(null, ep.save());
        system.assertEquals(null, ep.deleteTier());
        Test.stopTest();
    }
}